package com.lzy.wzy.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.lzy.wzy.constant.MyConstant;
import com.lzy.wzy.mapper.TemplateMapper;
import com.lzy.wzy.mapper.UserMapper;
import com.lzy.wzy.mapper.WorkMapper;
import com.lzy.wzy.model.*;
import com.lzy.wzy.sel.PtInfo;
import com.lzy.wzy.sel.TicketOrQuantity;
import com.lzy.wzy.token.MyUsernamePasswordToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.Cipher;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class WorkOrderUtils {
    private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");

    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private final Map<String, String> header = new LinkedHashMap<String, String>() {
        {
            put("product_number", "型号");
            put("production_date", "生产日期");
            put("product_code", "产品编码");
            put("production_quantity", "生产数量");
            put("work_order_number", "工单号");
            put("software_version", "软件产品版本");
        }
    };

    @Autowired
    private Cipher cipherEncode;

    @Autowired
    private Cipher cipherDecode;

    @Autowired
    private WorkMapper workMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TemplateMapper templateMapper;


    public String getWorkOrderNumber(String type, String serialNumber) {
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
        return type + date + serialNumber;
    }

    public String getSingleWorkOrderUpdateInfo(ModifyWorkOrderBean updateBefore, ModifyWorkOrderBean updateAfter) {
        Map<String, Object> befMap = JSON.parseObject(JSON.toJSONString(updateBefore), new TypeReference<Map<String, Object>>() {
        }, Feature.OrderedField);

        Map<String, Object> aftMap = JSON.parseObject(JSON.toJSONString(updateAfter), new TypeReference<Map<String, Object>>() {
        }, Feature.OrderedField);

        Map<String, String> resultMap = new LinkedHashMap<>();
        String key;
        String value;
        for (Map.Entry<String, Object> entry : befMap.entrySet()) {
            key = entry.getKey();
            value = String.valueOf(aftMap.get(key));
            if (!entry.getValue().equals(value)) {
                resultMap.put(key, value);
            }
        }
        return JSON.toJSONString(resultMap);
    }


    public Map<String, String> getMultipleModificationRecord(List<ModifyWorkOrderBean> updateBefore, List<ModifyWorkOrderBean> updateAfter) {
        Map<String, String> map = new HashMap<>();
        String updateInfo;
        if (updateBefore.size() == updateAfter.size()) {
            for (int i = 0; i < updateAfter.size(); i++) {
                updateInfo = getSingleWorkOrderUpdateInfo(updateBefore.get(i), updateAfter.get(i));
                if (StringUtils.isNotBlank(updateInfo)) {
                    map.put(updateAfter.get(i).getWorkOrderNumber(), updateInfo);
                }
            }
        }
        return map;
    }

    public Integer recordModificationInformation(String workOrderNumber, String modifyContent, int type, int templateId) {
        MyUsernamePasswordToken token = (MyUsernamePasswordToken) SecurityContextHolder.getContext().getAuthentication();
        String userUuid = (String) token.getPrincipal();
        ModifyRecordBean recordBean = new ModifyRecordBean();
        recordBean.setWorkOrderNumber(workOrderNumber);
        recordBean.setModifyTime(LocalDate.now());
        recordBean.setModifier(userUuid);
        recordBean.setModifyContent(modifyContent);
        recordBean.setType(type);
        recordBean.setTemplateId(templateId);
        return workMapper.saveModifyInfo(recordBean);
    }

    public String getWorkOrderTestProcessDataModifyInfo(List<LinkedHashMap<String, Object>> l1, List<LinkedHashMap<String, Object>> l2) {
        Map<String, Object> m1;
        Map<String, Object> m2;
        // 数据库此工单模板已存在数据条数
        int size1 = l1.size();
        // 提交条数
        int size2 = l2.size();
        // 初始化flag为true，后续避免多次put id
        boolean flag = true;
        Map<String, Object> map;
        //申明最终结果集
        List<Map<String, Object>> list = new ArrayList<>();
        //申明变量String val
        String val;

        String key;
        //获取最小size
        int targetSize = Math.min(size1, size2);
        //遍历两个集合，limit是 targetSize
        MyUsernamePasswordToken token = (MyUsernamePasswordToken) SecurityContextHolder.getContext().getAuthentication();
        List<String> authority = token.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());
        boolean match = Arrays.stream(MyConstant.Role.PRODUCT_G).noneMatch(authority::contains);
        for (int i = 0; i < targetSize; i++) {
            m1 = l1.get(i);
            m2 = l2.get(i);
            //利用equals比较两个map里面的元素是否相等
            if (!m1.equals(m2)) {
                //初始化数据存放map
                map = new LinkedHashMap<>();
                //遍历提交的map
                for (Map.Entry<String, Object> entry : m2.entrySet()) {
                    //初始化key
                    key = entry.getKey();
                    //初始化val 为数据库已存在的数据val
                    val = String.valueOf(m1.get(key));
                    //比较数据库和提交的val,如果同key val不同，进一步判断提交数据是否有workOrderNumber字段 因为出现此字段则为新增操作直接跳过
                    if (!entry.getValue().equals(val)) {
                        if (match
                                && StringUtils.isNotBlank(val)) {
                            throw new RuntimeException("不可修改哦，请异常上报。");
                        }
                        if ("workOrderNumber".equals(key))
                            continue;
                        //添加id，并将flag设为false
                        if (flag) {
                            map.put("id", m1.get("id"));
                            flag = false;
                        }
                        //如果后续数据还存在 id 字段数据直接抛出异常
                        if ("id".equals(key)) {
                            throw new RuntimeException("非法篡改数据");
                        }
                        map.put(key, entry.getValue());
                    }
                }
                map.put("operating", MyConstant.WorkOrderOperation.MODIFY);
                list.add(map);
            }
            flag = true;
        }
        if (size2 > size1) {
            for (int i = size1; i < size2; i++) {
                LinkedHashMap<String, Object> linkedHashMap = l2.get(i);
                map = new LinkedHashMap<>();
                Iterator<Map.Entry<String, Object>> iterator = linkedHashMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<String, Object> next = iterator.next();
                    if (StringUtils.isBlank(String.valueOf(next.getValue()))) {
                        iterator.remove();
                    } else {
                        map.put(next.getKey(), next.getValue());
                    }
                }
                map.put("operating", MyConstant.WorkOrderOperation.ADD);
                list.add(map);
            }
        } else {
            for (int i = size2; i < size1; i++) {
                LinkedHashMap<String, Object> linkedHashMap = l1.get(i);
                map = new LinkedHashMap<>();
                for (Map.Entry<String, Object> entry : linkedHashMap.entrySet()) {
                    val = String.valueOf(entry.getValue());
                    if (!val.equals("")) {
                        map.put(entry.getKey(), entry.getValue());
                    }
                }
                map.put("operating", MyConstant.WorkOrderOperation.DELETE);
                list.add(map);
            }
        }
        String s = JSON.toJSONString(list);
        System.out.println(JSON.toJSONString(s));
        return s;
    }

    public List<LinkedHashMap<String, Object>> encryptionProcessing(List<LinkedHashMap<String, Object>> list) {
        try {
            for (LinkedHashMap<String, Object> map : list) {
                map.put("id", encode(String.valueOf(map.get("id"))));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    public void decryptionProcessing(List<LinkedHashMap<String, Object>> list) {
        String id;
        try {
            for (LinkedHashMap<String, Object> map : list) {
                id = String.valueOf(map.get("id"));
                if (!"x".equals(id)) {
                    map.put("id", decode(id));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("非法篡改数据");
        }
    }

    public String encode(String id) throws Exception {
        return Hex.encodeHexString(cipherEncode.doFinal(id.getBytes()));
    }

    public String decode(String id) throws Exception {
        return new String(cipherDecode.doFinal(Hex.decodeHex(id)));
    }

    public void packageId(String worKOrderNumber, List<LinkedHashMap<String, Object>> before, List<LinkedHashMap<String, Object>> list) {
        int befSize = before.size();
        int afterSize = list.size();

        int minSize = Math.min(befSize, afterSize);
        Map<String, Object> map;

        Map<String, Object> afterMap;
        String id;
        /*
            第一种情况 数据库行数 d1 小于提交行数 d2 且d1>0 将d1 id 覆盖d2前面d1.size个 id 覆盖条数 d1.size
            第二种情况 数据库行数 d1 大于提交行数 d2 且d2>0 将d1 id 覆盖d2所有d2.size个 id 覆盖条数 d2.size
         */
        if (minSize > 0) {
            for (int i = 0; i < minSize; i++) {
                map = before.get(i);
                afterMap = list.get(i);
                try {
                    id = String.valueOf(map.get("id"));
                    if (StringUtils.isNotBlank(id)) {
                        afterMap.put("id", id);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException("非法篡改数据");
                }
            }
        }
        //第三种情况 数据库行数 d1 小于提交行数 d2 即为新增行 id 覆盖条数为 d2.size-d1.size 起点为 d1.size
        if (befSize < afterSize) {

            for (int i = befSize; i < afterSize; i++) {
                map = list.get(i);
                map.put("id", worKOrderNumber + LocalDateTime.now().format(dtf) + String.format("%02d", i + 1));
            }
        }
    }

    public void verifyTheReportedData(List<String> existedFields, List<String> subFields, List<LinkedHashMap<String, Object>> data) {
        boolean flag = true;
        int incr = 0;
        String msg = "非法篡改数据";
        int exitSize = existedFields.size() + 1;
        if (exitSize != subFields.size()) {
            flag = false;
        } else {
            for (LinkedHashMap<String, Object> map : data) {
                if (exitSize != map.size()) {
                    flag = false;
                    break;
                }
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    ++incr;
                    if (incr == 2) {
                        if ("".equals(entry.getValue())) {
                            msg = "禁止提交空数据行";
                            flag = false;
                            break;
                        }
                    }
                    if (incr > 2) {
                        break;
                    }
                }
                incr = 0;
            }
        }
        if (!flag) {
            throw new RuntimeException(msg);
        }
    }


    //获取序号
    public String getSerialNumber(String workType) {
        String serialNumber = workMapper.getThatDayLastWorkOrder(LocalDate.now().format(formatter), workType);
        if (null != serialNumber) {
            serialNumber = String.format("%02d", Integer.parseInt(serialNumber) + 1);
        } else {
            serialNumber = "01";
        }
        return serialNumber;
    }

    //获取表头信息
    public Map<String, Object> getHeaderInfo(Map<String, Object> map) {
        Map<String, Object> result = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : header.entrySet()) {
            result.put(entry.getValue(), map.getOrDefault(entry.getKey(), " "));
        }
        return result;
    }

    //校验单条修改工单提交的时间LocalDate.now().isBefore(date1) &&
    public boolean verifyDateFormat(LocalDate date1, LocalDate date2) {
        return date1.isBefore(date2) || date1.isEqual(date2);
    }


    public boolean verifyAllWorkOrderNumber(List<String> list) {
        return list.contains(MyConstant.WorkOrderStatus.FINISHED) || list.contains(MyConstant.WorkOrderStatus.CASECLOSE);
    }

    public void saveBulletin(String prefix, String name, String reason) {
        reason = reason.trim();
        MyUsernamePasswordToken token = (MyUsernamePasswordToken) SecurityContextHolder.getContext().getAuthentication();
        String userId = (String) token.getPrincipal();
        BulletinBean bulletinBean = new BulletinBean();
        bulletinBean.setBulletinContent(prefix + name + "\t原因：" + reason);
        bulletinBean.setAnnouncer(userId);
        bulletinBean.setBulletinTime(LocalDateTime.now());
        templateMapper.saveAnnouncementInformation(bulletinBean);
    }

    public void exportExcel(HttpServletResponse response, Map<String, Map<String, Map<String, Integer>>> map) throws IOException {
        if (null == map) {
            throw new RuntimeException("没有任何数据");
        }
        //创建poi导出数据对象
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook();
        //创建sheet页
        SXSSFSheet sheet = sxssfWorkbook.createSheet("生产统计报告");
        int firstRow = 0;
        int lastRow = 0;
        int firstCol = 0;
        int lastCol = 3;
        SXSSFRow title = sheet.createRow(firstRow);
        sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
        title.createCell(firstCol).setCellValue("产品编码");
        title.createCell(4).setCellValue("工单号");
        title.createCell(5).setCellValue("产品型号");
        title.createCell(6).setCellValue("新增在制");
        title.createCell(7).setCellValue("新增完工");
        title.createCell(8).setCellValue("新增入库");
        title.createCell(9).setCellValue("待生产");
        title.createCell(10).setCellValue("总在制");
        title.createCell(11).setCellValue("总完工");
        title.createCell(12).setCellValue("总入库");
        CellRangeAddress address;
        SXSSFRow row;
        Set<Map.Entry<String, Map<String, Map<String, Integer>>>> entries = map.entrySet();
        for (Map.Entry<String, Map<String, Map<String, Integer>>> entry : entries) {
            firstRow = lastRow + 1;
            lastRow += entry.getValue().size();
            address = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
            sheet.addMergedRegion(address);
            row = sheet.createRow(firstRow);
            row.createCell(firstCol).setCellValue(entry.getKey());
            dataFill(sheet, entry.getValue(), firstRow, lastCol, row);
            lastRow = address.getLastRow();
        }
        // 设置头信息
        response.setCharacterEncoding("UTF-8");
        //  response.setHeader("Set-Cookie", "fileDownload=true; path=/");
        response.setContentType("application/vnd.ms-excel");
        //一定要设置成xlsx格式
        //response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename + ".xlsx", "UTF-8"));
        //创建一个输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //写入数据
        sxssfWorkbook.write(outputStream);
        outputStream.flush();

        // 关闭
        outputStream.close();
        sxssfWorkbook.close();
    }

    public void checkTemplate(int templateId) {
        String status = templateMapper.getFirstLevelTemplateStatus(templateId);
        if (MyConstant.TemplateStatus.PENDING_REVIEW.equals(status) || null == status) {
            throw new RuntimeException("非法模板");
        }
    }

    private void dataFill(SXSSFSheet sheet, Map<String, Map<String, Integer>> data, int firstRow, int firstCol, SXSSFRow curRow) {
        SXSSFRow row;
        int temp = firstCol + 1;
        for (Map.Entry<String, Map<String, Integer>> entry : data.entrySet()) {
            if (firstRow == curRow.getRowNum()) {
                row = curRow;
            } else {
                row = sheet.createRow(firstRow);
            }
            row.createCell(temp).setCellValue(entry.getKey());
            row.createCell(++temp).setCellValue(workMapper.getProductNumberByWorkOrderNumber(entry.getKey()));
            for (Map.Entry<String, Integer> integerEntry : entry.getValue().entrySet()) {
                row.createCell(++temp).setCellValue(integerEntry.getValue());
            }
            firstRow++;
            temp = firstCol + 1;
        }
    }

    public boolean checkSuperAdmin(String userId) {
        String roleName = userMapper.getRoleByUserId(userId);
        return !MyConstant.Role.SUPER_ADMINISTRATOR.equals(roleName);
    }

    public boolean checkAdmin(String userId, String curId) {
        String roleName = userMapper.getRoleByUserId(userId);
        String curRoleName = userMapper.getRoleByUserId(curId);
        if (MyConstant.Role.SUPER_ADMINISTRATOR.equals(curRoleName)) {
            return !MyConstant.Role.SUPER_ADMINISTRATOR.equals(roleName);
        }
        return !MyConstant.Role.SUPER_ADMINISTRATOR.equals(roleName) && !MyConstant.Role.ADMIN.equals(roleName);
    }

    //集合拷贝
    public <T> List<T> deepCopy(List<T> src) {
        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
             ObjectOutputStream outputStream = new ObjectOutputStream(byteOut)
        ) {
            outputStream.writeObject(src);
            try (ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
                 ObjectInputStream inputStream = new ObjectInputStream(byteIn)
            ) {
                return (List<T>) inputStream.readObject();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return Collections.emptyList();
    }


    @Transactional(rollbackFor = Exception.class)
    @Scheduled(cron = "50 55 23 * * ?")
    public void stat() {
        List<String> productCode = workMapper.getAllProductCode();

        List<ProductStatBean> list = new ArrayList<>(productCode.size());
        List<PtInfo> ptInfos;
        ProductStatBean statBean;
        Integer quantity;
        Map<String, Integer> pack;
        LocalDate now = LocalDate.now();
        for (String code : productCode) {
            ptInfos = templateMapper.getProductTemplateDataByCode(code);
            if (ptInfos.isEmpty()) {
                quantity = workMapper.getProductQuantityByProductCode(code);
                statBean = new ProductStatBean(code, now, 0, 0, 0, quantity, 0, 0, 0);
                list.add(statBean);
                continue;
            }
            pack = pack(now.format(formatter), ptInfos, 0, 0, code);
            statBean = new ProductStatBean(
                    code, now, pack.get(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION)
                    , pack.get(MyConstant.WorkOrderStatus.ADDED_COMPLETION), pack.get(MyConstant.WorkOrderStatus.ADD_STORAGE)
                    , pack.get(MyConstant.WorkOrderStatus.TO_BE_PRODUCED), pack.get(MyConstant.WorkOrderStatus.IN_TOTAL), pack.get(MyConstant.WorkOrderStatus.TOTAL_FINISHED)
                    , pack.get(MyConstant.WorkOrderStatus.TOTAL_STORAGE)
            );
            list.add(statBean);
        }
        workMapper.saveProductStat(list);
        log.info("生产统计-" + now);
        reportStat(now);
    }

    private void reportStat(LocalDate now) {
        int year = now.getYear();
        int month = now.getMonthValue();
        int day = now.getDayOfMonth();
        String sYear = String.valueOf(year);
        List<Integer> type = new ArrayList<Integer>() {{
            add(2);
            add(3);
            add(4);
        }};
        for (Integer t : type) {
            Map<String, Map<String, Map<String, Integer>>> map = fillPack(year, month, day, t);
            switch (t) {
                case 2:
                    checkReportData(map, sYear);
                    break;
                case 3:
                    sYear = sYear + month;
                    checkReportData(map, sYear);
                    break;
                case 4:
                    sYear = String.format("%02d", year) + "-" + String.format("%02d", month) + "-" + String.format("%02d", day);
            }
            if (!map.isEmpty()) {
                templateMapper.saveReportData(map, sYear, t);
            }
        }
        log.info("生产报告统计-" + now);
    }

    private void checkReportData(Map<String, Map<String, Map<String, Integer>>> map, String statTime) {
        Iterator<Map.Entry<String, Map<String, Map<String, Integer>>>> iterator = map.entrySet().iterator();
        Map.Entry<String, Map<String, Map<String, Integer>>> next;
        Iterator<Map.Entry<String, Map<String, Integer>>> entryIterator;
        Map.Entry<String, Map<String, Integer>> mapEntry;
        List<Integer> list = new ArrayList<>();
        Integer idf;
        while (iterator.hasNext()) {
            next = iterator.next();
            entryIterator = next.getValue().entrySet().iterator();
            while (entryIterator.hasNext()) {
                mapEntry = entryIterator.next();
                idf = templateMapper.checkForPresenceReportData(next.getKey(), mapEntry.getKey(), statTime);
                if (idf != null) {
                    list.add(idf);
                }
            }
        }
        if (!list.isEmpty()) {
            templateMapper.deleteReportData(list, statTime);
        }
    }

    public Map<String, Map<String, Map<String, Integer>>> fillPack(int year, int month, int day, int type) {
        LocalDate first = workMapper.getFirstRecord();
        LocalDate last = workMapper.getLastRecord();
        int thisType = 0;
        int otherType = 0;
        int comp = 0;
        String date = null;
        switch (type) {
            case 2:
                if (year < first.getYear() || year > last.getYear()) {
                    throw new RuntimeException("没有可导出的数据");
                }
                thisType = 2;
                otherType = 6;
                comp = 1;
                break;
            case 3:
                if (month < 1 || month > 12) {
                    throw new RuntimeException("没有可导出的数据");
                }
                thisType = 3;
                otherType = 7;
                comp = 2;
                break;
            case 4: {
                if (year < first.getYear() || year > last.getYear() || month < 1 || month > 12 || day < 1 || day > 31) {
                    throw new RuntimeException("没有可导出的数据");
                }
                date = String.format("%02d", year) + "-" + String.format("%02d", month) + "-" + String.format("%02d", day);
                thisType = 1;
                otherType = 8;
                comp = 3;
            }
            default:
        }

        List<String> productCodes = workMapper.getAllProductCode();
        if (productCodes.isEmpty()) {
            throw new RuntimeException("没有任何数据");
        }
        Map<String, Map<String, Integer>> azyMap = new HashMap<>();
        //其他时间范围内的数据
        Map<String, Map<String, Map<String, Integer>>> otherData = fill(date, year, month, otherType, type, productCodes, comp, azyMap);

        //本次时间范围统计数据
        Map<String, Map<String, Map<String, Integer>>> thisData = fill(date, year, month, thisType, type, productCodes, comp, azyMap);

        String key;

        String childKey;
        //当天map
        Map<String, Integer> cur;
        //之前
        Map<String, Integer> before;
        Map<String, Map<String, Integer>> temp;
        //临时 other map
        Map<String, Map<String, Integer>> otherTemp;

        //临时thismAP
        Map<String, Integer> thisTemp;

        int totalStore;

        int totalSum;

        int total;

        int inTotal;
        //按照最终统计此处 thisdata和otherdata的数据size应一致，且产品编码数量和工单号都一致
        if (!otherData.isEmpty()) {
            for (Map.Entry<String, Map<String, Map<String, Integer>>> entry : thisData.entrySet()) {
                key = entry.getKey();
                otherTemp = otherData.get(key);
                if (!otherTemp.isEmpty()) {
                    temp = entry.getValue();
                    for (Map.Entry<String, Map<String, Integer>> val : temp.entrySet()) {
                        totalStore = 0;
                        childKey = val.getKey();
                        thisTemp = temp.get(childKey);
                        if (thisTemp.containsKey(MyConstant.WorkOrderStatus.TOTAL_STORAGE)) {
                            totalStore = thisTemp.get(MyConstant.WorkOrderStatus.TOTAL_STORAGE);
                            thisTemp.remove(MyConstant.WorkOrderStatus.TOTAL_STORAGE);
                        }
                        before = otherTemp.get(childKey);
                        cur = val.getValue();

                        total = cur.get(MyConstant.WorkOrderStatus.TOTAL);
                        cur.remove(MyConstant.WorkOrderStatus.TOTAL);
                        inTotal = cur.get(MyConstant.WorkOrderStatus.IN_TOTAL) + cur.get(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION) + before.get(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION);
                        cur.put(MyConstant.WorkOrderStatus.IN_TOTAL, Math.max(inTotal, 0));
                        if (0 > inTotal) {
                            cur.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, cur.get(MyConstant.WorkOrderStatus.TO_BE_PRODUCED) + inTotal);
                        }
                        cur.put(MyConstant.WorkOrderStatus.TOTAL_FINISHED, cur.get(MyConstant.WorkOrderStatus.ADDED_COMPLETION) + before.get(MyConstant.WorkOrderStatus.ADDED_COMPLETION));
                        totalStore += cur.get(MyConstant.WorkOrderStatus.ADD_STORAGE) + before.get(MyConstant.WorkOrderStatus.ADD_STORAGE);
                        if (totalStore > 0) {
                            cur.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, 0);
                            cur.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, 0);
                            cur.put(MyConstant.WorkOrderStatus.IN_TOTAL, 0);
                            cur.put(MyConstant.WorkOrderStatus.TOTAL_FINISHED, 0);
                        }
                        cur.put(MyConstant.WorkOrderStatus.TOTAL_STORAGE, totalStore);
                        totalSum = cur.get(MyConstant.WorkOrderStatus.IN_TOTAL) + cur.get(MyConstant.WorkOrderStatus.TOTAL_FINISHED) + cur.get(MyConstant.WorkOrderStatus.TOTAL_STORAGE);

                        cur.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, Math.max(0, total - totalSum));

                        temp.put(childKey, cur);
                    }
                    thisData.put(key, temp);
                }
            }
        }
        return thisData;
    }

    private Map<String, Map<String, Map<String, Integer>>> fill(String date, int year, int month, int type, int sType, List<String> productCodes, int comp, Map<String, Map<String, Integer>> azyMap) {
        //申明变量模板id
        Integer templateId;
        //申明变量求和sum
        int sum;
        //申明变量val接收待生产
        int val;
        //申明变量接收工单生产数量
        int quantity;
        //申明动态key
        String key;

        //申明最终结果集map
        Map<String, Map<String, Map<String, Integer>>> map = new LinkedHashMap<>(16);
        //申明结果集wre 存储 结构 key：工单号 <key：生产情况 val：数量>
        Map<String, Map<String, Integer>> wre;
        //临时接收wre结果集相同 工单号的val
        Map<String, Integer> beforeMap;
        //返回数据处理后的map
        Map<String, Integer> objectMap;
        //通过产品编码获取编码模板映射表数据
        List<PtInfo> ptInfos = null;

        int del;
        //申明变量接收结案工单的入库数量
        int temp;
        //申明工单号结果集
        List<String> code;

        //存储本次日期之前的纯修改操作， 意味着此机器之前并未完成。
        Map<String, Integer> zyMap;

        int toBeProduced;

        int finished;
        LocalDate earliestCreateTime;
        LocalDate now;
        String time;
        //遍历产品编码集合
        for (String productCode : productCodes) {
            earliestCreateTime = workMapper.getTheEarliestCreateTime(productCode);
            if (earliestCreateTime == null) {
                throw new RuntimeException("导出失败,该编码未使用");
            }
            now = LocalDate.now();
            switch (sType) {
                case 2:
                    if (earliestCreateTime.getYear() > year) {
                        continue;
                    }
                    ptInfos = templateMapper.getPtInfoByCodeAndYear(productCode, String.valueOf(now.getYear()));
                    break;
                case 3:
                    if (earliestCreateTime.getMonthValue() > month && earliestCreateTime.getYear() >= year) {
                        continue;
                    }
                    time = String.valueOf(now.getYear()) + now.getMonthValue();
                    ptInfos = templateMapper.getPtInfoByCodeAndMonth(productCode, time);
                    break;
                case 4:
                    if (earliestCreateTime.isAfter(LocalDate.parse(date))) {
                        continue;
                    }
                    ptInfos = templateMapper.getPtInfoByCodeAndTime(productCode, now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    break;
            }
            wre = new LinkedHashMap<>();
            if (ptInfos == null || ptInfos.isEmpty()) {
//                map.put(productCode, wre);
                continue;
            }
            //为空直接跳过
//            if (ptInfos.isEmpty()) {
//                if (map.containsKey(productCode)) {
//                    continue;
//                }
//                // pcodeTempBeans = templateMapper.queryReworkTemplateIdByCode(productCode);
//                //   if (pcodeTempBeans.isEmpty()) {
//                List<TicketOrQuantity> works = workMapper.getWorksByProductCode(productCode);
//                if (!works.isEmpty()) {
//                    LinkedHashMap<String, Integer> re;
//                    for (TicketOrQuantity work : works) {
//                        re = new LinkedHashMap<>(8);
//                        re.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, 0);
//                        re.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, 0);
//                        re.put(MyConstant.WorkOrderStatus.ADD_STORAGE, 0);
//                        re.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, work.getProductionQuantity());
//                        re.put(MyConstant.WorkOrderStatus.TOTAL, work.getProductionQuantity());
//                        re.put(MyConstant.WorkOrderStatus.IN_TOTAL, 0);
//                        re.put(MyConstant.WorkOrderStatus.TOTAL_FINISHED, 0);
//                        re.put(MyConstant.WorkOrderStatus.TOTAL_STORAGE, 0);
//                        wre.put(work.getWorkOrderNumber(), re);
//                    }
//                    map.put(productCode, wre);
////                    }
////                    continue;
//                }
//            }
            //初始化 LinkedHashMap 因为后续要遍历到excel所有申明为有序map

            // int tempId;
            //遍历编码模板结果集
            String workOrder;
            // List<String> reWorks = new ArrayList<>();
            for (PtInfo pt : ptInfos) {
                //给模板id复制
                templateId = pt.getTemplateId();
                //  tempId = templateId;
                workOrder = pt.getWorkOrderNumber();

                quantity = pt.getQuantity();
                //通过产品编码获取对应的工单集合
                //code = workMapper.getWorkOrderByCode(pcodeTempBean.getProductCode());
                //遍历工单集合
                //for (String workOrder : code) {
                //如果工单为返修工单则模板id为 返修工单与模板映射表的模板id
//                    if (workOrder.startsWith("F")) {
//                        if (reWorks.contains(workOrder))
//                            continue;
//                        templateId = templateMapper.getTemplateIdByRework(workOrder);
//                        //reWorks.add(workOrder);
//                    }
                //若模板id不为null，意为此返修工单已经绑定模板，直接进行生产数据统计
                //azymap存储  key 工单号   value 为 zymap  若存在则直接获取
                if (azyMap.containsKey(workOrder)) {
                    zyMap = azyMap.get(workOrder);
                } else {
                    zyMap = new HashMap<>();
                }
                //数据统计
                objectMap = statisticalData(date, year, month, templateId, type, comp, zyMap, pt);
                //将before修改存入
                azyMap.put(workOrder, zyMap);
                //若 工单为存在生产记录 objectMap应为null ，而且wre结果集存在此工单则直接跳过，否则  objectMap为null wre结果集不存在此工单则 申明一个空 map集合
                if (objectMap == null && wre.containsKey(workOrder)) {
                    continue;
                } else if (objectMap == null) {
                    objectMap = new LinkedHashMap<>();
                }
                del = 0;
                //申明变量待生产
                toBeProduced = 0;
                //若生产统计map不存在在制key 则 put 0
                if (!objectMap.containsKey(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION)) {
                    objectMap.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, 0);
                }
                if (objectMap.containsKey(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM)) {
                    del = objectMap.get(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM);
                    objectMap.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, objectMap.get(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION) + del);
                }
                //若生产统计map不存在完工key 则put 0
                if (!objectMap.containsKey(MyConstant.WorkOrderStatus.ADDED_COMPLETION)) {
                    objectMap.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, 0);
                } else {
                    finished = objectMap.get(MyConstant.WorkOrderStatus.ADDED_COMPLETION);
                    objectMap.remove(MyConstant.WorkOrderStatus.ADDED_COMPLETION);
                    objectMap.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, finished);
                }
                if (objectMap.containsKey(MyConstant.WorkOrderStatus.TO_BE_PRODUCED)) {
                    //接收单台机器持续多天操作本日期完工的数量
                    toBeProduced = objectMap.get(MyConstant.WorkOrderStatus.TO_BE_PRODUCED);
                    //保证有序删除 待生产
                    objectMap.remove(MyConstant.WorkOrderStatus.TO_BE_PRODUCED);
                }
                //若生产统计map不存在入库key 则put 0
                if (!objectMap.containsKey(MyConstant.WorkOrderStatus.ADD_STORAGE)) {
                    objectMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, 0);
                } else {
                    //若存在入库key 则 用临时遍历temp接收入库数量，将入库key删除，重新put进去。保证最后所有数据统计map key顺序一致
                    temp = objectMap.get(MyConstant.WorkOrderStatus.ADD_STORAGE);
                    objectMap.entrySet().removeIf(stringIntegerEntry -> MyConstant.WorkOrderStatus.ADD_STORAGE.equals(stringIntegerEntry.getKey()));
                    objectMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, temp);
                }
                //只对当日 ，当月 ，当年 操作进行待生产统计
                if (type <= 3) {
                    //sum = 新增在制 + 新增完工 + 新增入库
                    sum = objectMap.values().stream().mapToInt(Integer::intValue).sum();
                    //不存在此工单
                    if (!wre.containsKey(workOrder)) {
                        //获取此工单生产数量
                        //quantity = workMapper.getProductQuantityByWorkOrderNumber(workOrder);
                        // 待生产 = 生产数量 - 绝对值 sum - 纯删除在制操作
                        objectMap.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, quantity - Math.abs(sum) - del);
                        // put 生产生产数量
                        objectMap.put(MyConstant.WorkOrderStatus.TOTAL, quantity);
                    }
                }
                    /*
                        注： 此机器可能经历多天操作，新增 ，  n（修改） 然后本期完工  = 1
                     */
                //若 此完工数量大于0
                if (toBeProduced > 0) {
                    //将总在制 数量- toBeProduced
                    objectMap.put(MyConstant.WorkOrderStatus.IN_TOTAL, -toBeProduced);
                } else {
                    //否则为0，为保证结果 key 顺序一样
                    objectMap.put(MyConstant.WorkOrderStatus.IN_TOTAL, 0);
                }
                //若wre结果集存在此工单且为统计本次提交的时间统计数据则对待生产数量进行操作,
                if (wre.containsKey(workOrder)) {
                    beforeMap = wre.get(workOrder);
                    //遍历数据统计map  key为 完工，在制，入库，待生产
                    Set<Map.Entry<String, Integer>> entries = objectMap.entrySet();
                    for (Map.Entry<String, Integer> entry : entries) {
                        key = entry.getKey();
                        if (beforeMap.containsKey(key)) {
                            //只对本期操作统计待生产
                            if (type <= 3) {
                                val = entry.getValue();
                                beforeMap.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, beforeMap.get(MyConstant.WorkOrderStatus.TO_BE_PRODUCED) - Math.abs(val) - del);
                            }
                            //获取本次数据统计key value= 前一次map数据 + 本次数据 是为了保证同编码多工单情况下操作
                            beforeMap.put(key, beforeMap.get(key) + entry.getValue());
                        }
                    }
                    wre.put(workOrder, beforeMap);
                } else {
                    //不存在则直接put
                    wre.put(workOrder, objectMap);
                }
                objectMap.entrySet().removeIf(stringIntegerEntry -> stringIntegerEntry.getKey().equals(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM));
                objectMap.entrySet().removeIf(stringIntegerEntry -> stringIntegerEntry.getKey().equals(MyConstant.WorkOrderStatus.DEL_COMPLETION));
                //}
            }
            //往最终结果集 put 产品编码和 工单数据统计集合
            map.put(productCode, wre);
        }
        return map;
    }

    public Map<String, Integer> pack(String date, List<PtInfo> ptInfos, int year, int month, String productCode) {
        Map<String, Integer> re;
        LocalDate earliestCreateTime = workMapper.getTheEarliestCreateTime(productCode);
        if (earliestCreateTime != null && earliestCreateTime.isAfter(LocalDate.parse(date))) {
            re = new LinkedHashMap<>();
            re.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, 0);
            re.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, 0);
            re.put(MyConstant.WorkOrderStatus.ADD_STORAGE, 0);
            re.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, 0);
            re.put(MyConstant.WorkOrderStatus.IN_TOTAL, 0);
            re.put(MyConstant.WorkOrderStatus.TOTAL_FINISHED, 0);
            re.put(MyConstant.WorkOrderStatus.TOTAL_STORAGE, 0);
            return re;
        }
        Map<String, Integer> zyMap = new HashMap<>();
        //获取其他时间的生产数据
        Map<String, Integer> other = dataPack(date, ptInfos, year, month, productCode, 8, zyMap);
        //获取本次查询的生产数据
        re = dataPack(date, ptInfos, year, month, productCode, 1, zyMap);

        int delInSystem = 0;
        if (re.containsKey(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM)) {
            delInSystem = re.get(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM);
            re.remove(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM);
        }
        int delCompletion = 0;
        if (re.containsKey(MyConstant.WorkOrderStatus.DEL_COMPLETION)) {
            delCompletion = re.get(MyConstant.WorkOrderStatus.DEL_COMPLETION);
            re.remove(MyConstant.WorkOrderStatus.DEL_COMPLETION);
        }

        int beforeDelCompletion = 0;
        if (other.containsKey(MyConstant.WorkOrderStatus.DEL_COMPLETION)) {
            beforeDelCompletion = other.get(MyConstant.WorkOrderStatus.DEL_COMPLETION);
        }

        if (!re.containsKey(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION)) {
            re.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, 0);
        }
        int finished = 0;
        if (!re.containsKey(MyConstant.WorkOrderStatus.ADDED_COMPLETION)) {
            re.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, 0);
        } else {
            finished = re.get(MyConstant.WorkOrderStatus.ADDED_COMPLETION);
            //若存在调整位置
            re.remove(MyConstant.WorkOrderStatus.ADDED_COMPLETION);
            re.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, Math.max(finished, 0));
        }
        if (!re.containsKey(MyConstant.WorkOrderStatus.ADD_STORAGE)) {
            re.put(MyConstant.WorkOrderStatus.ADD_STORAGE, 0);
        } else {
            //获取入库数量
            int store = re.get(MyConstant.WorkOrderStatus.ADD_STORAGE);
            //若存在调整位置
            re.remove(MyConstant.WorkOrderStatus.ADD_STORAGE);

            re.put(MyConstant.WorkOrderStatus.ADD_STORAGE, store);
        }


        //获取产品编码下生产总和
        Integer quantity = workMapper.getProductQuantityByProductCode(productCode);
        //计算以前在制数量
        int beforeInSystem = 0;
        if (other.containsKey(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION)) {
            beforeInSystem = other.get(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION);
        }
        int delBeforeInSystem = 0;
        if (other.containsKey(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM)) {
            delBeforeInSystem = other.get(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM);
        }
        //计算之前完工数量
        int beforeFinished = 0;
        if (other.containsKey(MyConstant.WorkOrderStatus.ADDED_COMPLETION)) {
            beforeFinished = other.get(MyConstant.WorkOrderStatus.ADDED_COMPLETION);
        }
        //获取当天在制数量
        int inSystemCount = re.get(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION);
        //总共在制数量=当天在制数量 +当前删除在制数量+ 之前在制数量
        int inTotal = inSystemCount + delInSystem + beforeInSystem + delBeforeInSystem;

        inSystemCount += delInSystem;

        re.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, Math.max(0, inSystemCount));

        //若当天在制数量小于0 则只触发删除操作，则归零处理
        int beforeStore = 0;
        if (other.containsKey(MyConstant.WorkOrderStatus.ADD_STORAGE)) {
            beforeStore = other.get(MyConstant.WorkOrderStatus.ADD_STORAGE);
        }
        int curStore = 0;
        if (re.containsKey(MyConstant.WorkOrderStatus.ADD_STORAGE)) {
            curStore = re.get(MyConstant.WorkOrderStatus.ADD_STORAGE);
        }


        //总完工数量 = 当前完工数量 + 当前删除完工数量 + 之前完工数量
        int totalFinished = finished + delCompletion + beforeFinished + beforeDelCompletion;

        //待生产数量=总数量-本时间范围已生产数量-其他时间范围生产数量 （同编码）
        int toBeProduced;
        if (re.containsKey(MyConstant.WorkOrderStatus.TO_BE_PRODUCED)) {
            toBeProduced = re.get(MyConstant.WorkOrderStatus.TO_BE_PRODUCED);
            re.remove(MyConstant.WorkOrderStatus.TO_BE_PRODUCED);
            inTotal -= toBeProduced;
        }

        if (inTotal < 0) {
            inTotal = 0;
        }

        if (totalFinished < 0) {
            totalFinished = 0;
        }
        int totalStorage = 0;
        if (re.containsKey(MyConstant.WorkOrderStatus.TOTAL_STORAGE)) {
            totalStorage = re.get(MyConstant.WorkOrderStatus.TOTAL_STORAGE);
            re.remove(MyConstant.WorkOrderStatus.TOTAL_STORAGE);
        }
        //总共入库数量 = 之前入库数量 + 当前入库数量
        totalStorage += beforeStore + curStore;

        toBeProduced = quantity - inTotal - totalFinished - totalStorage;

        re.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, toBeProduced);

        //添加总在制
        re.put(MyConstant.WorkOrderStatus.IN_TOTAL, inTotal);
        //put总完工
        re.put(MyConstant.WorkOrderStatus.TOTAL_FINISHED, totalFinished);
        //put总入库
        re.put(MyConstant.WorkOrderStatus.TOTAL_STORAGE, totalStorage);
        return re;
    }

    private Map<String, Integer> dataPack(String date, List<PtInfo> ptInfos, int year, int month, String productCode, int type, Map<String, Integer> zyMap) {
        Integer templateId;
        List<Map<String, Integer>> list = new ArrayList<>();
        Map<String, List<Map<String, Integer>>> map = new LinkedHashMap<>();
        Map<String, Integer> objectMap;
        //List<String> code;
        int tempId;
        //List<String> temp = new ArrayList<>();
        for (PtInfo pt : ptInfos) {
            templateId = pt.getTemplateId();
            //tempId = templateId;
//            code = workMapper.getWorkOrderByCode(pcodeTempBean.getProductCode());
//            for (String workOrder : code) {
//                if (workOrder.startsWith("F")) {
//                    if (temp.contains(workOrder)) {
//                        continue;
//                    }
//                    templateId = templateMapper.getTemplateIdByRework(workOrder);
//                    if (templateId == null) {
//                        continue;
//                    }
//                    temp.add(workOrder);
//                }
//                if (templateId == null) {
//                    templateId = tempId;
//                }
            objectMap = statisticalData(date, year, month, templateId, type, 3, zyMap, pt);
            if (objectMap != null) {
                list.add(objectMap);
            }
            // templateId = tempId;
//            }
        }
        map.put(productCode, list);

        String key;

        //利用map对统计结果数量进行遍历相加
        Map<String, Integer> re = new LinkedHashMap<>();
        List<Map<String, Integer>> m1;
        Set<Map.Entry<String, Integer>> m2;
        for (Map.Entry<String, List<Map<String, Integer>>> entry : map.entrySet()) {
            m1 = entry.getValue();
            for (Map<String, Integer> integerMap : m1) {
                m2 = integerMap.entrySet();
                for (Map.Entry<String, Integer> item : m2) {
                    key = item.getKey();
                    if (re.containsKey(key)) {
                        re.put(key, re.get(key) + item.getValue());
                    } else {
                        re.put(key, item.getValue());
                    }
                }
            }
        }
        return re;
    }

    /*
     * @Author wzy
     * @Description //TODO 生产数据处理
     * @Date 2021/8/23 15:56
     * @Param * @param: date
     * @param: year
     * @param: month
     * @param: workOrderNumber
     * @param: templateId
     * @param: type
     * @param: comp
     * @param: zyMap
     * @return java.util.Map<java.lang.String,java.lang.Integer>
     **/
    private Map<String, Integer> statisticalData(String date, int year, int month, int templateId, int type, int comp, Map<String, Integer> zyMap, PtInfo ptInfo) {
        List<ModifyRecordBean> recordBeans;
        String time;
        String workOrderNumber = ptInfo.getWorkOrderNumber();
        switch (type) {
            case 1:
                time = date;
                recordBeans = templateMapper.getTodayProductionData(time, workOrderNumber, 2, templateId);
                //查询例子 2021年 8 月 25日月份数据
                // recordBeans = templateMapper.getProduceRecordByMonth(year, month, workOrderNumber, 2, templateId);
                break;
            case 2:
                //查询 例 2021 年数据
                recordBeans = templateMapper.getProduceRecordByYear(year, workOrderNumber, 2, templateId);
                break;
            case 3:
                //查询 例 2021-8 月份数据
                recordBeans = templateMapper.getProduceRecordByMonth(year, month, workOrderNumber, 2, templateId);
                break;
//            case 4:
//                time = String.valueOf(year) + month + day;
//                recordBeans=templateMapper.getTodayProductionData(time,workOrderNumber,2,templateId);
//                break;
//            case 5:
//                ///查询 例 2021-8 月之前的数据
//                time = String.valueOf(year) + month;
//                recordBeans = templateMapper.getProductionRecordsOfOtherMonths(time, workOrderNumber, 2, templateId);
//            break;
            case 6:
                //查询 例 2021 年之前的数据
                recordBeans = templateMapper.getProductionRecordsOfOtherYears(year, workOrderNumber, 2, templateId);
                break;
            case 7:
                //查询 例 2021-8 月之前的数据
                time = String.valueOf(year) + month;
                recordBeans = templateMapper.getProductionRecordsOfOtherMonths(time, workOrderNumber, 2, templateId);
                break;
            case 8:
                time = date;
                recordBeans = templateMapper.getProductionDataBeforeToday(time, workOrderNumber, 2, templateId);
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + type);
        }

        //申明返回结果集
        Map<String, Integer> resultMap = new LinkedHashMap<>();

        boolean finishFlag;
        //申明数据量机器个数count
        int count;
        //获取工单状态
//        IdentifierStatus identifierStatus = workMapper.getIdentifierAndStatus(workOrderNumber);
        String status = ptInfo.getStatus();

        if (ptInfo.getIdentifier() == 1) {
            LocalDate curTime;
            if (date == null) {
                curTime = LocalDate.now();
            } else {
                curTime = LocalDate.parse(date);
            }
            //CloseAndAntiClose closingTime = workMapper.getClosingAndAntiClosingTime(workOrderNumber);
            LocalDate closeTime = ptInfo.getClosingDate();
            LocalDate antiCloseTime = ptInfo.getAntiClosingTime();
            LocalDate lastClosingTime = ptInfo.getLastClosingTime();
            String tableName = ptInfo.getTableName();
            if (MyConstant.WorkOrderStatus.FINISHED.equals(status) || MyConstant.WorkOrderStatus.InSystem.equals(status)) {
                if (type <= 3) {
                    switch (comp) {
                        case 1:
                            int closeYear = closeTime.getYear();
                            int antiCloseYear = antiCloseTime.getYear();
                            if (closeYear <= year
                                    && year < antiCloseYear) {
                                resultMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber));
                                return resultMap;
                            }
                            break;
                        case 2:
                            int closeMonth = closeTime.getMonthValue();
                            int antiCloseMonth = antiCloseTime.getMonthValue();
                            if (closeMonth <= month
                                    && month < antiCloseMonth) {
                                resultMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber));
                                return resultMap;
                            }
                            break;
                        case 3:
                            if ((closeTime.isEqual(curTime) || closeTime.isBefore(curTime) || curTime.isEqual(lastClosingTime))
                                    && curTime.isBefore(antiCloseTime)) {
                                resultMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber));
                                return resultMap;
                            }
                            break;
                    }
                } else {
                    if ((antiCloseTime.isBefore(curTime) || antiCloseTime.isEqual(curTime))
                            || (month > 0 && antiCloseTime.getMonthValue() > month)
                            || (year > 0 && antiCloseTime.getYear() > year)) {
                        log.info("next");
                    } else {
                        return null;
                    }
                }
            } else if (MyConstant.WorkOrderStatus.CASECLOSE.equals(status)) {
                //若工单再次结案且反结案大于当前时间则也入库
                //&& (antiCloseTime.isAfter(curTime) || closeTime.isEqual(curTime) || curTime.isAfter(closeTime))
                //                        && (curTime.isAfter(lastClosingTime) || curTime.isEqual(lastClosingTime))
                if (type <= 3
                ) {
                    //若查询时间为上一次结案时间，并且结案时间等于当前时间或者当前时间小于反结案时间
                    if ((antiCloseTime.isAfter(curTime) || closeTime.isEqual(curTime))
                            && (curTime.isEqual(lastClosingTime) || curTime.isAfter(lastClosingTime))) {
                        resultMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber));
                        return resultMap;
                        //否则当前时间在结案时间之后，并且当前时间在上一次结案时间之后
                    } else if (curTime.isAfter(closeTime) || curTime.isAfter(lastClosingTime)) {
                        resultMap.put(MyConstant.WorkOrderStatus.TOTAL_STORAGE, templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber));
                        return resultMap;
                    }
                } else if (curTime.isEqual(lastClosingTime) || curTime.isAfter(lastClosingTime)) {
                    return null;
                }
            }
        } else {
            //若此工单为结案工单则此工单下所有已经在制，完工机器都为入库机器不做后续统计
            if (MyConstant.WorkOrderStatus.CASECLOSE.equals(status)) {
                //获取工单结案时间
                LocalDate closingTime = ptInfo.getClosingDate();
                //获取数据表名
                String tableName = ptInfo.getTableName();
                //comp 1 2 3 代表 年 月 日
                switch (comp) {
                    case 1:
                        if ((type == 2 && closingTime.getYear() == year) || (type == 6 && closingTime.getYear() < year)) {
                            resultMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber));
                            // return resultMap;
                        }
                        return resultMap;
                    case 2:
                        if (closingTime.getYear() == year &&
                                ((closingTime.getMonthValue() == month && type == 3) ||
                                        (closingTime.getMonthValue() < month && type == 7))) {
                            resultMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber));
                            // return resultMap;
                        }
                        return resultMap;
                    case 3:
                        LocalDate now = LocalDate.parse(date);
                        //获取机器个数
                        count = templateMapper.getMachinesCountByWorkOrderNumber(tableName, workOrderNumber);
                        //若为本期查询，并且 结案日期=查询日期
                        if (type == 1) {
                            if (closingTime.isEqual(now)) {
                                resultMap.put(MyConstant.WorkOrderStatus.ADD_STORAGE, count);
                            }
                            if (closingTime.isBefore(now)) {
                                resultMap.put(MyConstant.WorkOrderStatus.TOTAL_STORAGE, count);
                            }
                            return resultMap;
                            //若为before查询，且结案时间等于查询时间 标记为true
                        } else if (type == 8 && (closingTime.isEqual(now) || closingTime.isBefore(now))) {
                            //delStore = true;
                            return resultMap;
                        }
                }
            }
        }

        if (recordBeans.isEmpty() && zyMap.isEmpty()) {
            return null;
        }
        List<LinkedHashMap<String, String>> allField = templateMapper.getThreeLeaveTemplateIdAndNameByOneId(templateId);
        //初始化存放模板 name和field的map
        Map<String, Object> fieldMap = new LinkedHashMap<>();
        //封装 列map
        for (LinkedHashMap<String, String> field : allField) {
            fieldMap.put(field.get("field_name"), field.get("template_name"));
        }
        //将操作记录按照时间排序
        recordBeans.sort(Comparator.comparing(ModifyRecordBean::getModifyTime));
        //初始化分组list
        List<Map<String, Object>> list = new ArrayList<>();

        //遍历所有操作content将其转换为 List<Map<String,Object> 并添加修改人
        List<Map<String, Object>> maps;
        for (ModifyRecordBean recordBean : recordBeans) {

            maps = JSON.parseObject(recordBean.getModifyContent(), new TypeReference<List<Map<String, Object>>>() {
            }, Feature.OrderedField);

            list.addAll(maps);
        }
        //申明字段key
        String key;

        //将所有操作记录进行id分组
        Map<Object, List<Map<String, Object>>> listMap = list.stream().collect(Collectors.groupingBy(map -> map.get("id")));

        //存放此次遍历结果
        Map<String, Object> temp;


        //最终数据集合
        Map<String, Map<String, Object>> r2Map = new LinkedHashMap<>();

        //申明数据标记map
        Map<String, Boolean> flagMap = new LinkedHashMap<>();

        int del = 0;


        boolean flag;

        int fieldSize = fieldMap.size();
        String id;
        int size;
        int tsCount = 0;
        int tempSize;
        int delFinished = 0;
        List<Map<String, Object>> value;

        Set<Map.Entry<String, Object>> entries;

        //遍历分组后的 map
        for (Map.Entry<Object, List<Map<String, Object>>> entry : listMap.entrySet()) {
            finishFlag = false;
            //容器初始化
            temp = new LinkedHashMap<>();
            flag = false;
            id = (String) entry.getKey();
            value = entry.getValue();

            //遍历每一组里面的map
            for (Map<String, Object> map : value) {

                //若出现 delete操作，且这一组里面有数据，则回滚这一组所有数据，此处直接清掉掉map ,否则 自增del,
                if (MyConstant.WorkOrderOperation.DELETE.equals(map.get("operating"))) {
                    if (temp.size() > 0) {
                        temp.clear();
//                        temp = null;
                        del++;
                    } else if (map.size() - 3 == fieldSize) {
                        delFinished++;
                    } else {
                        del++;
                    }
                    break;
                }
                //标记新增操作
                if (MyConstant.WorkOrderOperation.ADD.equals(map.get("operating"))) {
                    flag = true;
                }
                if (map.size() > 2) {
                    //遍历字段map
                    entries = fieldMap.entrySet();
                    for (Map.Entry<String, Object> field : entries) {
                        //key赋值
                        key = field.getKey();
                        //若操作记录有操作过此字段则向 temp put此字段和操作后的数据,并记录 对应的操作者
                        if (map.containsKey(key)) {
                            temp.put(key, map.get(key));
                        }
                    }
                }
            }
            //若数据存放map没有出现delete操作向map存放机器id和数据大小, <=3代表本期操作

            temp.entrySet().removeIf(stringObjectEntry -> stringObjectEntry.getValue().equals(""));
            //接收数据大小
            tempSize = temp.size();
            //若为 before查询 并且 数据大小小于字段总长度，则 put 机器id 和 历次修改之后最终长度
            if (type > 3 && tempSize < fieldSize) {
                zyMap.put(id, tempSize);
            }
            //若为本期查询 并且数据大小小于字段总长度，则尝试获取本机器id，若存在此机器并且本期修改操作结果长度 + before操作数据长度 = 字段总长度 则代表这台机器当期完工
            if (type <= 3 && tempSize <= fieldSize) {
                if (zyMap.containsKey(id)) {
                    if (zyMap.get(id) + tempSize >= fieldSize) {
                        finishFlag = true;
                        tsCount++;
                    }
                }
            }
            if (!finishFlag) {
                //存储 机器 id ，value 为是否进行了新增操作
                flagMap.put(id, flag);
                //存储机器id和操作数据
                r2Map.put(id, temp);
            }
        }

        //申明完工数量=0
        int finishCount = 0;
        //申明在制数量=0
        int inSystemCount = 0;


//        if (!delStore) {
        //遍历结果
        for (Map.Entry<String, Map<String, Object>> entry : r2Map.entrySet()) {
            size = entry.getValue().size();
            key = entry.getKey();
            //若数据长度 = 字段长度 则为新增完工
            if (size == fieldSize) {
                finishCount++;
                //若大于0小于数据长度，切出现新增操作则为新增在制
            } else if (size < fieldSize && flagMap.get(key)) {
                inSystemCount++;
            }
        }
        if (!r2Map.isEmpty() || !zyMap.isEmpty()) {
            //新增在制数量 = 新增在制 - 纯删除在制
            resultMap.put(MyConstant.WorkOrderStatus.ADD_IN_PRODUCTION, inSystemCount);
            resultMap.put(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM, -del);
            //完工数量= 当天新增完工数量 - 多天操作本期完工数量 - 纯删除完工数量
            resultMap.put(MyConstant.WorkOrderStatus.ADDED_COMPLETION, finishCount + tsCount);
            resultMap.put(MyConstant.WorkOrderStatus.DEL_COMPLETION, -delFinished);
            //若出现 tscount>0 ，保证待生产加上这个 tscount
            if (tsCount > 0) {
                resultMap.put(MyConstant.WorkOrderStatus.TO_BE_PRODUCED, tsCount);
            }
        } else {
            //若存在del >0 ，只进行了删除在制操作，且结果集为空
            if (del > 0) {
                log.info("工单" + workOrderNumber + "删除机器" + del + "台");
                resultMap.put(MyConstant.WorkOrderStatus.DEL_IN_SYSTEM, -del);
            }
            //delFinished >0 ，只进行了删除完工操作，且结果集为空
            if (delFinished > 0) {
                log.info("工单" + workOrderNumber + "删除完工机器" + delFinished + "台");
                resultMap.put(MyConstant.WorkOrderStatus.DEL_COMPLETION, -delFinished);
            }
        }
        // }
        return resultMap;
    }

}
